package fi.lappalainen.cachemanager;

import fi.lappalainen.geoapp.utils.CacheList;
import fi.lappalainen.geoapp.utils.GeoCache;
import fi.lappalainen.geoapp.utils.GeocacheParser;
import java.io.File;
import java.io.FilenameFilter;
import java.io.IOException;
import java.util.List;

/**
 * CahceManager luokka huolehtii kätköjen käsittelystä. Hoitaa tiedon
 * säilömisen ja hakutoimintoihin tarvittavat toiminnat.
 * @author mika.j.lappalainen@gmail.com
 * @version 1.0
 * @since 1.0
 */
public class CacheManager {

    /*
     * Luokka, jonka avulla suodatetaan tiedostolistauksesta vain GPX-tiedostot.
     * @author mika.j.lappalainen@gmail.com
     * @version 1.0
     * @since 1.0
     */
    class GPXFilter implements FilenameFilter {

        public boolean accept(File dir, String name) {
            return (name.endsWith(".gpx"));
        }
    }

    /*
     * Lista, johon tallennetaan tiedostoista luetut kätköt.
     */
    private CacheList caches;

    /**
     * Oletustmuodostin, luo CacheManager-olion oletusarvoilla.
     */
    public CacheManager() {
        caches = new CacheList(5);
    }

    /**
     * Yhdistää parametrinä tulleesta kansiosta löytyvistä GPX-tiedostoista
     * geokätköt yhteen GPX-tiedostoon.
     * @param sourceFolder Kansio, josta GPX-tiedostoja etsitään.
     * @param destination Tiedosto, johon löytyneet kätköt tallennetaan.
     * @return true, jos yhdistäminen onnistui, muuten false.
     */
    public boolean joinCachesFromFolder(String sourceFolder, String destination) {
        this.caches.clear();
        this.readCachesFromFolder(sourceFolder);
        File f1 = new File(sourceFolder);
        String dest = null;
        try {
            dest = f1.getCanonicalPath();
        } catch (IOException ex) {
            return false;
        }
        dest = dest + f1.separator + destination;
        if(GeocacheParser.writeCachesToGPXFile(caches, dest)) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * Yhdistää parametrinä tulleet GPX-tiedostot yhdeksi tiedostoksi.
     * @param filenames Yhdistettävät GPX-tiedostot pilkulla erotettuina.
     * @param destination Tiedosto, johon yhdistettävät tiedot kirjoitetaan.
     */
    public void joinCachesByFilename(String filenames, String destination) {
        caches.clear();
        String[] files = filenames.split(",");
        for (int idx = 0; idx < files.length; idx++) {
            List<GeoCache> cachestemp =
                    GeocacheParser.readCachesFromGPXFile(files[idx]);
            caches.addAll(cachestemp);
        }
        GeocacheParser.writeCachesToGPXFile(caches, destination);
    }

    /**
     * Laskee yksittäisen GPX-tiedoston sisältämien kätköjen määrän.
     * @param filename Tiedosto, josta kätköt lasketaan.
     * @return Tiedostossa olevien kätköjen määrä.
     */
    public int countCachesInFile(String filename) {
        CacheList cachestemp = GeocacheParser.readCachesFromGPXFile(filename);
        return cachestemp.size();

    }

    /**
     * Lukee yksittäisen GPX-tiedoston sisältämät kätköt.
     * @param filename Tiedosto, josta kätköt luetaan.
     */
    public boolean readCachesFromFile(String filename) {
        CacheList cachestemp = GeocacheParser.readCachesFromGPXFile(filename);
        if (cachestemp != null) {
            this.caches.addAll(cachestemp);
            return true;
        } else {
            return false;
        }
    }

    /*
     * Listaa hakemistosta kaikki .gpx päätteiset tiedostot ja
     * lukee kätköjen tiedot näistä tiedostoista.
     * @param folderPath Hakemisto, josta kätköt luetaan
     * @return true jos luku onnistuu, muuten false.
     */
    private boolean readCachesFromFolder(String folderPath) {
        File f1 = new File(folderPath);
        String folder = null;
        if(f1.isDirectory()){
            try {
                folder = f1.getCanonicalPath();
            } catch (IOException ex) {
                return false;
            }
            folder = folder + f1.separator;
        int i;
        String[] ls;
        FilenameFilter filter = new GPXFilter();
        ls = f1.list(filter);
        for (i = 0; i < ls.length; i++) {
            CacheList cachestemp =
                    GeocacheParser.readCachesFromGPXFile(folder + ls[i]);
            this.caches.addAll(cachestemp);
        }
        }
        return true;
    }

    /**
     * Listaa luettujen kätköjen nimet ja ID:t
     * @return Palauttaa 2-ulotteisen merkkijonotaulukon jonka ensimmäinen
     * sarake sisältää kätkön ID:n ja toinen kätkön nimen.
     */
    public String[][] listNamesAndIds() {
        return this.caches.listNamesAndIds();
    }

    /**
     * Hakee listalta kätkön nimen perusteella.
     * @param name Kätkön nimi, jota etsitään.
     * @return Nimen perusteella löydetty kätkö-oli
     */
    public GeoCache findCacheByName(String name) {
        return this.findCacheByName(name);
    }

    /**
     * Hakee listalta kätkön ID:n perusteella.
     * @param id Id, jolla kätköä etsitään.
     * @return Id:n perusteella löydetty kätköolio.
     */
    public GeoCache findCacheById(String id) {
        return this.caches.findCacheById(id);
    }
}
